package co.yixiang.modules.mp.serviceimpl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import co.yixiang.common.exception.BadRequestException;
import co.yixiang.common.exception.EntityExistException;
import co.yixiang.common.service.impl.BaseServiceImpl;
import co.yixiang.common.utils.FileUtil;
import co.yixiang.common.utils.QueryHelpPlus;
import co.yixiang.common.utils.ValidationUtil;
import co.yixiang.dozer.service.IGenerator;
import co.yixiang.modules.mp.entity.domain.YxHelp;
import co.yixiang.modules.mp.entity.domain.YxHelpCategory;
import co.yixiang.modules.mp.entity.dto.YxHelpCategoryDto;
import co.yixiang.modules.mp.entity.dto.YxHelpCategoryQueryCriteria;
import co.yixiang.modules.mp.entity.vo.YxHelpCategoryVo;
import co.yixiang.modules.mp.entity.vo.YxHelpCategoryVoF;
import co.yixiang.modules.mp.mapper.YxHelpCategoryMapper;
import co.yixiang.modules.mp.service.YxHelpCategoryService;
import co.yixiang.modules.mp.service.YxHelpService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

@Service
//@CacheConfig(cacheNames = "yxArticle")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class YxHelpCategoryServiceImpl extends BaseServiceImpl<YxHelpCategoryMapper, YxHelpCategory> implements YxHelpCategoryService {
    @Autowired
    private YxHelpService helpService;

    private final IGenerator generator;
    public YxHelpCategoryServiceImpl(IGenerator generator){ this.generator = generator;}


    @Override
    public List<YxHelpCategoryVoF> queryAllByVo() {
        List<YxHelpCategory> list = this.list(new LambdaQueryWrapper<YxHelpCategory>().eq(YxHelpCategory::getIsDel, 0));
        return  generator.convert(list, YxHelpCategoryVoF.class);
    }

    @Override
    public Map<String, Object> queryAll(YxHelpCategoryQueryCriteria criteria, Pageable pageable) {
        getPage(pageable);
        PageInfo<YxHelpCategory> page = new PageInfo<>(queryAll(criteria));
        Map<String, Object> map = new LinkedHashMap<>(2);
        map.put("content", generator.convert(page.getList(), YxHelpCategoryDto.class));
        map.put("totalElements", page.getTotal());
        return map;
    }

    @Override
    public List<YxHelpCategory> queryAll(YxHelpCategoryQueryCriteria criteria) {
        return baseMapper.selectList(QueryHelpPlus.getPredicate(YxHelpCategory.class, criteria));
    }

    @Override
    public void download(List<YxHelpCategoryDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (YxHelpCategoryDto yxArticle : all) {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("分类名称", yxArticle.getName());
            map.put("层级", yxArticle.getLevel());
            map.put("上级分类ID", yxArticle.getParentId());
            map.put("排序", yxArticle.getSort());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    @Override
    public Map<String, Object> buildTree(List<YxHelpCategoryDto> yxHelpCategoryDtos) {
        List<YxHelpCategoryDto> trees = new ArrayList<>();
        Set<Long> ids = new HashSet<>();
        for (YxHelpCategoryDto helpCategoryDto : yxHelpCategoryDtos) {
            if (helpCategoryDto.getParentId() == 0) {
                trees.add(helpCategoryDto);
            }
            for (YxHelpCategoryDto it : yxHelpCategoryDtos) {
                if (it.getParentId().equals(helpCategoryDto.getId())) {
                    if (helpCategoryDto.getChildren() == null) {
                        helpCategoryDto.setChildren(new ArrayList<>());
                    }
                    helpCategoryDto.getChildren().add(it);
                    ids.add(it.getId());
                }
            }
        }
        Map<String, Object> map = new HashMap<>(2);
        if (trees.size() == 0) {
            trees = yxHelpCategoryDtos.stream().filter(s -> !ids.contains(s.getId())).collect(Collectors.toList());
        }
        map.put("content", trees);
        map.put("totalElements", yxHelpCategoryDtos.size());
        return map;
    }

    @Override
    public List<YxHelpCategoryVo> buildYxHelpCategorys(List<YxHelpCategoryDto> yxHelpCategoryDtos) {
        List<YxHelpCategoryVo> list = new LinkedList<>();
        yxHelpCategoryDtos.forEach(helpCategoryDTO -> {
                    if (helpCategoryDTO != null) {
                        List<YxHelpCategoryDto> helpCategoryDtoList = helpCategoryDTO.getChildren();
                        YxHelpCategoryVo helpCategoryVo = new YxHelpCategoryVo();
                        helpCategoryVo.setName(helpCategoryDTO.getName());
                        // 一级目录需要加斜杠，不然会报警告
                        helpCategoryVo.setHidden(helpCategoryDTO.getHidden());
                        // 如果不是外链
                        if (helpCategoryDtoList != null && helpCategoryDtoList.size() != 0) {
                            helpCategoryVo.setAlwaysShow(true);
                            helpCategoryVo.setChildren(buildYxHelpCategorys(helpCategoryDtoList));
                            // 处理是一级菜单并且没有子菜单的情况
                        } else if (helpCategoryDTO.getParentId() == 0) {
                           YxHelpCategoryVo helpCategoryVo1 = new YxHelpCategoryVo();
                            // 非外链
                            helpCategoryVo1.setName(helpCategoryVo.getName());
                            helpCategoryVo.setName(null);
                            List<YxHelpCategoryVo> list1 = new ArrayList<>();
                            list1.add(helpCategoryVo1);
                            helpCategoryVo.setChildren(list1);
                        }
                        list.add(helpCategoryVo);
                    }
                }
        );
        return list;
    }

    @Override
    public Object getYxHelpCategoryTree(List<YxHelpCategory> yxHelpCategories) {
        List<Map<String, Object>> list = new LinkedList<>();
        yxHelpCategories.forEach(helpCategory -> {
                    if (helpCategory != null) {
                        List<YxHelpCategory> helpCategoryList = findByPid(helpCategory.getId());
                        Map<String, Object> map = new HashMap<>(16);
                        map.put("id", helpCategory.getId());
                        map.put("label", helpCategory.getName());
                        if (helpCategoryList != null && helpCategoryList.size() != 0) {
                            map.put("children", getYxHelpCategoryTree(helpCategoryList));
                        }
                        list.add(map);
                    }
                }
        );
        return list;
    }

    @Override
    public Set<YxHelpCategory> getDeleteYxHelpCategorys(List<YxHelpCategory> yxHelpCategoryList, Set<YxHelpCategory> yxHelpCategorySet) {
        // 递归找出待删除的菜单
        for (YxHelpCategory helpCategory1 : yxHelpCategoryList) {
            yxHelpCategorySet.add(helpCategory1);
            List<YxHelpCategory> helpCategorys = findByPid(helpCategory1.getId());
            if (helpCategorys != null && helpCategorys.size() != 0) {
                getDeleteYxHelpCategorys(helpCategorys, yxHelpCategorySet);
            }
        }
        return yxHelpCategorySet;
    }

    @Override
    public List<YxHelpCategory> findByPid(long pid) {
        return list(new LambdaQueryWrapper<YxHelpCategory>().eq(YxHelpCategory::getParentId, pid));
    }

    @Override
    public void delete(Set<YxHelpCategory> yxHelpCategorySet) {
        List<Long> ids = new ArrayList<>(yxHelpCategorySet.size());
        for (YxHelpCategory helpCategory : yxHelpCategorySet) {
            ids.add(helpCategory.getId());
        }
        final List<YxHelp> list = helpService.list(new LambdaQueryWrapper<YxHelp>().eq(YxHelp::getIsDel, Boolean.FALSE).in(YxHelp::getCid, ids));
        if(CollectionUtil.isNotEmpty(list)) {
            throw new BadRequestException("分类下有文章不能删除");
        }
        removeBatchByIds(ids);
    }

    @Override
    public void update(YxHelpCategory resources) {
        if (resources.getId().equals(resources.getParentId())) {
            throw new BadRequestException("上级不能为自己");
        }
        YxHelpCategory helpCategory = this.getById(resources.getId());
        ValidationUtil.isNull(helpCategory.getId(), "Permission", "id", resources.getId());

        final YxHelpCategory parent = isExitParent(resources);
        QueryWrapper<YxHelpCategory> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("name",resources.getName());
        YxHelpCategory YxHelpCategory1 = this.getOne(queryWrapper);
        if (YxHelpCategory1 != null && !YxHelpCategory1.getId().equals(helpCategory.getId())) {
            throw new EntityExistException(YxHelpCategory.class, "name", resources.getName());
        }

        helpCategory.setId(resources.getId());
        helpCategory.setName(resources.getName());
        helpCategory.setParentId(resources.getParentId());
        helpCategory.setLevel(parent.getLevel()+1);
        helpCategory.setSort(resources.getSort());
        this.saveOrUpdate(helpCategory);
    }



    @Override
    public YxHelpCategoryDto create(YxHelpCategory resources) {

        if (this.getOne(new LambdaQueryWrapper<YxHelpCategory>().eq(YxHelpCategory::getName, resources.getName())) != null) {
            throw new EntityExistException(YxHelpCategory.class, "name", resources.getName());
        }
        resources.setLevel(1);
        if (resources.getParentId() != 0) {
            final YxHelpCategory parent = isExitParent(resources);
            resources.setLevel(parent.getLevel()+1);
        }
        resources.setIsDel(0);
        this.save(resources);
        return generator.convert(resources, YxHelpCategoryDto.class);
    }


    /**
     * 公共方法提取出来-判断父级元素是否存在
     * @param resources
     */
    private YxHelpCategory isExitParent(YxHelpCategory resources) {

        final YxHelpCategory parent = this.getOne(new LambdaQueryWrapper<YxHelpCategory>().eq(YxHelpCategory::getId, resources.getParentId()));
        if(ObjectUtil.isEmpty(parent)) {
            throw new BadRequestException("父分类不存在");
        }
        return parent;
    }
}
